{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# VeighNa XT 数据服务演示\n",
    "\n",
    "本演示基于vnpy_xt模块，展示如何连接迅投研数据服务、获取股票和ETF数据、订阅行情以及查询合约信息。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 导入必要的库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入VeighNa核心库\n",
    "import sys\n",
    "sys.path.append('d:/git/liugejiao/vnpy')  # 添加包含vnpy模块的目录\n",
    "sys.path.append('d:/git/liugejiao')  # 添加项目根目录\n",
    "from vnpy.trader.constant import Exchange, Interval\n",
    "from vnpy.trader.object import SubscribeRequest, HistoryRequest\n",
    "\n",
    "# 导入XT相关模块\n",
    "sys.path.append('d:/git/liugejiao/vnpy_xt')  # 添加vnpy_xt的父目录\n",
    "from vnpy_xt import Datafeed, XtGateway\n",
    "\n",
    "# 导入其他必要库\n",
    "import pandas as pd\n",
    "from datetime import datetime, timedelta\n",
    "import time"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 初始化数据服务 (Datafeed)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建并初始化数据服务实例\n",
    "datafeed = Datafeed()\n",
    "\n",
    "# 设置为使用客户端连接模式\n",
    "# 通过设置username为\"client\"，使datafeed使用本地XtMiniQmt连接\n",
    "# 而不是尝试连接远程服务器\n",
    "datafeed.username = \"client\"\n",
    "\n",
    "# 初始化数据服务 - 使用客户端方式连接\n",
    "# 注意：使用客户端连接前需要确保迅投客户端已启动\n",
    "print(\"初始化数据服务中...\")\n",
    "if datafeed.init():\n",
    "    print(\"数据服务初始化成功！\")\n",
    "else:\n",
    "    print(\"数据服务初始化失败，请检查迅投客户端是否已启动。\")\n",
    "    print(\"请确保XtMiniQmt.exe或QMT投研版已启动并登录\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 获取股票历史数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义获取历史数据的函数\n",
    "def get_stock_history(symbol, exchange, interval, days=30):\n",
    "    \"\"\"获取股票历史数据\"\"\"\n",
    "    # 计算起止时间\n",
    "    end = datetime.now()\n",
    "    start = end - timedelta(days=days)\n",
    "    \n",
    "    # 创建历史数据请求\n",
    "    req = HistoryRequest(\n",
    "        symbol=symbol,\n",
    "        exchange=exchange,\n",
    "        interval=interval,\n",
    "        start=start,\n",
    "        end=end\n",
    "    )\n",
    "    \n",
    "    # 查询数据\n",
    "    bars = datafeed.query_bar_history(req)\n",
    "    \n",
    "    if bars:\n",
    "        # 转换为DataFrame格式便于查看和分析\n",
    "        df = pd.DataFrame(\n",
    "            [[bar.datetime, bar.open_price, bar.high_price, bar.low_price, bar.close_price, bar.volume]\n",
    "             for bar in bars],\n",
    "            columns=[\"datetime\", \"open\", \"high\", \"low\", \"close\", \"volume\"]\n",
    "        )\n",
    "        return df\n",
    "    else:\n",
    "        print(f\"无法获取 {symbol} 的历史数据\")\n",
    "        return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 获取上证指数的日线数据\n",
    "sz_index_df = get_stock_history(\"000001\", Exchange.SSE, Interval.DAILY, days=60)\n",
    "print(\"上证指数日线数据：\")\n",
    "if sz_index_df is not None:\n",
    "    print(sz_index_df.tail(10))\n",
    "\n",
    "# 获取贵州茅台的日线数据\n",
    "maotai_df = get_stock_history(\"600519\", Exchange.SSE, Interval.DAILY, days=60)\n",
    "print(\"贵州茅台日线数据：\")\n",
    "if maotai_df is not None:\n",
    "    print(maotai_df.tail(10))\n",
    "\n",
    "# 获取沪深300ETF的日线数据\n",
    "etf300_df = get_stock_history(\"510300\", Exchange.SSE, Interval.DAILY, days=60)\n",
    "print(\"沪深300ETF日线数据：\")\n",
    "if etf300_df is not None:\n",
    "    print(etf300_df.tail(10))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. 订阅实时行情"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建事件引擎用于行情订阅\n",
    "from vnpy.event import EventEngine\n",
    "from vnpy.trader.event import EVENT_TICK\n",
    "\n",
    "# 创建事件引擎实例\n",
    "event_engine = EventEngine()\n",
    "event_engine.start()\n",
    "\n",
    "# 创建交易网关实例用于行情订阅\n",
    "gateway = XtGateway(event_engine, \"XT\")\n",
    "\n",
    "# 配置连接参数\n",
    "setting = {\n",
    "    \"token\": \"\",  # 客户端模式下token可以留空\n",
    "    \"股票市场\": \"是\",\n",
    "    \"期货市场\": \"否\",\n",
    "    \"期权市场\": \"否\",\n",
    "    \"仿真交易\": \"是\",  # 请根据实际情况修改\n",
    "    \"账号类型\": \"股票\",\n",
    "    \"QMT路径\": r\"D:/gjzqqmt_ceshi\",  # 请修改为您的QMT安装路径\n",
    "    \"资金账号\": \"40743071\"  # 替换为您的资金账号\n",
    "}\n",
    "\n",
    "# 连接交易网关\n",
    "print(\"连接交易网关中...\")\n",
    "gateway.connect(setting)\n",
    "# 等待连接完成\n",
    "time.sleep(3)\n",
    "\n",
    "# 定义行情事件处理函数\n",
    "def process_tick_event(event):\n",
    "    \"\"\"处理行情事件\"\"\"\n",
    "    tick = event.data\n",
    "    print(f\"行情推送: {tick.vt_symbol} 最新价: {tick.last_price} 成交量: {tick.volume} 时间: {tick.datetime}\")\n",
    "\n",
    "# 注册行情事件监听\n",
    "event_engine.register(EVENT_TICK, process_tick_event)\n",
    "\n",
    "# 订阅股票行情\n",
    "def subscribe_market_data(symbol, exchange):\n",
    "    \"\"\"订阅指定合约的行情\"\"\"\n",
    "    req = SubscribeRequest(\n",
    "        symbol=symbol,\n",
    "        exchange=exchange\n",
    "    )\n",
    "    gateway.subscribe(req)\n",
    "    print(f\"已订阅 {symbol}.{exchange.value} 的行情\")\n",
    "\n",
    "# 订阅多个股票\n",
    "subscribe_market_data(\"000001\", Exchange.SZSE)  # 平安银行\n",
    "subscribe_market_data(\"600519\", Exchange.SSE)  # 贵州茅台\n",
    "subscribe_market_data(\"510300\", Exchange.SSE)  # 沪深300ETF\n",
    "\n",
    "# 等待行情推送\n",
    "print(\"等待行情推送...(按Ctrl+C可停止)\")\n",
    "try:\n",
    "    time.sleep(30)  # 等待30秒接收行情\n",
    "    print(\"等待30秒接收行情... 完成\")\n",
    "except KeyboardInterrupt:\n",
    "    print(\"停止接收行情\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. 查询合约信息"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义查询合约信息的函数\n",
    "from xtquant import xtdata\n",
    "\n",
    "def get_contract_info(symbol, exchange):\n",
    "    \"\"\"获取合约基本信息\"\"\"\n",
    "    # 转换为迅投格式的代码\n",
    "    if exchange == Exchange.SSE:\n",
    "        xt_symbol = f\"{symbol}.SH\"\n",
    "    elif exchange == Exchange.SZSE:\n",
    "        xt_symbol = f\"{symbol}.SZ\"\n",
    "    else:\n",
    "        return None\n",
    "    \n",
    "    try:\n",
    "        # 获取合约详细信息\n",
    "        info = xtdata.get_instrument_detail(xt_symbol)\n",
    "        if info:\n",
    "            print(f\"{symbol}.{exchange.value} 合约信息：\")\n",
    "            print(f\"合约名称: {info.get('InstrumentName', 'N/A')}\")\n",
    "            print(f\"合约代码: {info.get('InstrumentID', 'N/A')}\")\n",
    "            print(f\"交易单位: {info.get('VolumeMultiple', 'N/A')}\")\n",
    "            print(f\"最小变动价位: {info.get('PriceTick', 'N/A')}\")\n",
    "            print(f\"涨跌停幅度: ±{(info.get('UpStopPrice', 0) - info.get('LastClosePrice', 1))/info.get('LastClosePrice', 1)*100:.2f}%\")\n",
    "            return info\n",
    "    except Exception as e:\n",
    "        print(f\"获取合约信息失败: {str(e)}\")\n",
    "    return None\n",
    "\n",
    "# 获取合约信息示例\n",
    "get_contract_info(\"000001\", Exchange.SZSE)  # 平安银行\n",
    "get_contract_info(\"600519\", Exchange.SSE)  # 贵州茅台\n",
    "get_contract_info(\"510300\", Exchange.SSE)  # 沪深300ETF"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6. 关闭连接"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 关闭交易网关\n",
    "print(\"关闭交易网关...\")\n",
    "gateway.close()\n",
    "\n",
    "# 停止事件引擎\n",
    "print(\"停止事件引擎...\")\n",
    "event_engine.stop()\n",
    "\n",
    "print(\"数据服务演示完成！\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7. 注意事项"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. 使用本演示前，请确保：\n",
    "   - 已安装vnpy_xt模块\n",
    "   - 已安装并启动迅投QMT客户端\n",
    "   - 已正确配置QMT路径\n",
    "\n",
    "2. 行情订阅后，需要等待一段时间才能收到推送数据\n",
    "\n",
    "3. 本演示主要针对股票和ETF市场的数据查询功能"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
